package tddc77.yahtzee.swing;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import tddc77.yahtzee.Die;

/**
 *
 * @author John Törnblom (johto012), Mikael Silvén (miksi016)
 */
public class DiePanel extends javax.swing.JPanel
        implements PropertyChangeListener
{

    private Die die;
    private Color color;

    public DiePanel()
    {
        this(new Die());
        die.roll();
    }

    public DiePanel(Die die)
    {
        this.die = die;

        die.addPropertyChangeListener(this);
        color = (die.isOnHold() ? Color.RED : Color.BLACK);
        setBorder(new javax.swing.border.LineBorder(color, 3, true));

        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        setBackground(new java.awt.Color(255, 255, 255));
        setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 3, true));
        addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                formMouseClicked(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 30, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 30, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents

    private void formMouseClicked(java.awt.event.MouseEvent evt)//GEN-FIRST:event_formMouseClicked
    {//GEN-HEADEREND:event_formMouseClicked
        die.setOnHold(!die.isOnHold());
    }//GEN-LAST:event_formMouseClicked

    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables
    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        //Only render if the die has any dots
        if (die.getNumber() > 0)
        {
            paintDie((Graphics2D) g);
        }
    }

    private void paintDie(Graphics2D g2d)
    {
        float diameter = 0;

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(color);

        //Make sure all the dots will fit.
        if (getHeight() > getWidth())
        {
            diameter = (float) getWidth() / (float) 7.0;
        }
        else
        {
            diameter = (float) getHeight() / (float) 7.0;
        }

        //Paint 3x3 black dots
        for (float x = 1; x < 7; x += 2)
        {
            for (float y = 1; y < 7; y += 2)
            {
                if (shouldIPaint((int) x / 2, (int) y / 2))
                {
                    paintDot(g2d, x * getWidth() / 7, y * getHeight() / 7,
                            diameter);
                }
            }
        }
    }

    /**
     * Determens if the dot at possition (x, y) should be painted or not by
     * looking at the dies current number. (x, y) = (0, 0) represents the upper
     * left dot, (x, y) = (2, 2) represents the bottom right dot.
     *
     * @param x the x chordinate
     * @param y the y chordinate
     *
     * @return if there should be a dot at possition (x, y).
     */
    private boolean shouldIPaint(int x, int y)
    {
        //Allways paint upper left dot, unless the number is one
        if (x == 0 && y == 0 && die.getNumber() > 1)
        {
            return true;
        }
        //Allways paint bottom right dot, unless the number is one
        if (x == 2 && y == 2 && die.getNumber() > 1)
        {
            return true;
        }
        //For all odd numbers, paint the middle dot
        if (x == 1 && y == 1 && (die.getNumber() & 1) == 1)
        {
            return true;
        }
        //For fours, fives and sixes, paint all dots with an even x chordinate
        //AND even y chordinates (All corners of the die).
        if (die.getNumber() > 3 && x % 2 == 0 && y % 2 == 0)
        {
            return true;
        }
        //For sixes, paint all dots with an even x chordinate
        if (die.getNumber() > 5 && x % 2 == 0)
        {
            return true;
        }
        return false;
    }

    /**
     * Paints a round dot with the upper-left corner is at pixel (x, y)
     * with the diameter d
     *
     * @param x the x chordinate
     * @param y the y chordinate
     * @param d the d diameter
     */
    private void paintDot(Graphics2D g2d, float x, float y, float d)
    {
        Ellipse2D circle = new Ellipse2D.Float(x, y, d, d);
        g2d.fill(circle);
    }

    public void propertyChange(PropertyChangeEvent evt)
    {
        String property = evt.getPropertyName();

        //The number changed, update the view
        if (property.equals(Die.NUMBER_PROPERTY))
        {
            repaint();
        }
        //The onHold state changed, repaint with new color
        else if (property.equals(Die.ON_HOLD_PROPERTY))
        {
            color = (die.isOnHold() ? Color.RED : Color.BLACK);
            setBorder(new javax.swing.border.LineBorder(color, 3, true));
            repaint();
        }
    }
}
